/**
 * @file wa_iconlist.c
 *
 */

 /*********************
 *      INCLUDES
 *********************/
#include "wa_conf.h"
#if USE_WA_ICONLIST != 0
#include "wa_iconlist.h"
#include "wa_pid.h"
#include "wa_input.h"

 /*********************
 *      DEFINES
 *********************/

 /**********************
 *      TYPEDEFS
 **********************/

 /**********************
 *  STATIC PROTOTYPES
 **********************/
static wa_obj_callback ancestor_callback;
static void wa_iconlist_callback(wa_sign* sign);
static void wa_iconlist_invalidate_bitmap(wa_obj* iconlist);
static void wa_iconlist_invalidate_text(wa_obj* iconlist);
#if USE_WA_ANIM != 0
static void wa_iconlist_anim_exec_cb(void* obj, int32_t value);
static void wa_iconlist_anim_finish_cb(wa_anim* anim);
static void wa_iconlist_anim_start_cb(wa_anim* anim);
#endif
static int32_t wa_iconlist_select_to_pos(wa_obj* iconlist);

/**********************
 *  STATIC VARIABLES
 **********************/


 /**********************
 *      MACROS
 **********************/

 /**********************
 *   GLOBAL FUNCTIONS
 **********************/
 /**
 * iconlist module init
 */
void wa_iconlist_module_init(void)
{
}

/**
* create a iconlist
* @param par
* @return iconlist obj
*/
wa_obj* wa_iconlist_create(wa_obj* par)
{
	wa_obj* new_iconlist;
	wa_iconlist_ext* iconlist_ext;

	new_iconlist = wa_obj_create(par, NULL);
	if (new_iconlist == NULL)
	{
		return new_iconlist;
	}

	if (ancestor_callback == NULL)
	{
		ancestor_callback = wa_obj_get_callback(new_iconlist);
	}
	iconlist_ext = wa_obj_malloc_ext_attr(new_iconlist, sizeof(wa_iconlist_ext));
	if (iconlist_ext == NULL)
	{
		return NULL;
	}

#if USE_WA_ANIM != 0
	iconlist_ext->anim = wa_anim_create();
#endif
	iconlist_ext->anim_enable = wa_nok;
	iconlist_ext->switch_time_length = 500;

	iconlist_ext->roll_type = WA_ICONLIST_ROLL_TYPE_HOR;
	iconlist_ext->option_bitmap = NULL;
	iconlist_ext->option_text = NULL;
	iconlist_ext->option_cnt = 0;
	iconlist_ext->text_font = NULL;

	iconlist_ext->fore_color = WA_COLOR_FOREGROUND;
	iconlist_ext->back_color = WA_COLOR_BACKGROUND;

	iconlist_ext->select = 0;
	iconlist_ext->space = 0;

	iconlist_ext->roll_pos = 0;
	iconlist_ext->roll_rel_x = 0;
	iconlist_ext->roll_rel_y = 0;
	iconlist_ext->roll_w = 0;
	iconlist_ext->roll_h = 0;

	iconlist_ext->text_type = WA_ICONLIST_TEXT_TYPE_NORMAL_HOR;
	iconlist_ext->text_rel_x = 0;
	iconlist_ext->text_rel_y = 0;
	iconlist_ext->text_s_x = 0;
	iconlist_ext->text_s_y = 0;
	iconlist_ext->text_pos_x = 0;
	iconlist_ext->text_pos_y = 0;

	iconlist_ext->arrow_enable = wa_nok;
	iconlist_ext->arrow_w = 0;
	iconlist_ext->arrow_h = 0;
	iconlist_ext->arrow_interval = 0;

	wa_obj_set_callback(new_iconlist, wa_iconlist_callback);

	return new_iconlist;
}

/**
* iconlist add option
* @param iconlist
* @param bitmap
* @param text
*/
void wa_iconlist_add_option(wa_obj* iconlist, wa_bitmap* bitmap, char* text)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);

	if ((ext->option_bitmap == NULL) || (ext->option_text == NULL))
	{
		ext->option_bitmap = wa_malloc(sizeof(wa_bitmap*));
		ext->option_bitmap[0] = bitmap;
		ext->option_text = wa_malloc(sizeof(char*));
		ext->option_text[0] = wa_malloc(strlen((const char*)text) + 1);
		strcpy((char*)(ext->option_text[0]), (char*)text);
		ext->option_cnt = 1;
	}
	else
	{
		wa_bitmap** bp;
		char** tp;
		ext->option_cnt++;
		bp = wa_malloc(sizeof(wa_bitmap*) * ext->option_cnt);
		memcpy(bp, ext->option_bitmap, sizeof(wa_bitmap*) * (ext->option_cnt - 1));
		wa_free(ext->option_bitmap);
		ext->option_bitmap = bp;
		ext->option_bitmap[ext->option_cnt - 1] = bitmap;

		tp = wa_malloc(sizeof(char*) * ext->option_cnt);
		memcpy(tp, ext->option_text, sizeof(char*) * (ext->option_cnt - 1));
		wa_free(ext->option_text);
		ext->option_text = tp;
		ext->option_text[ext->option_cnt - 1] = wa_malloc(strlen((const char*)text) + 1);
		strcpy((char*)(ext->option_text[ext->option_cnt - 1]), (char*)text);
	}
	wa_obj_invalidate(iconlist);
}

/**
* iconlist clear option
* @param iconlist
*/
void wa_iconlist_clear_option(wa_obj* iconlist)
{
	uint32_t i;
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	if (ext->option_bitmap != NULL)
	{
		wa_free(ext->option_bitmap);
	}
	if (ext->option_text != NULL)
	{
		for (i = 0; i < ext->option_cnt; i++)
		{
			wa_free(ext->option_text[i]);
		}
		wa_free(ext->option_text);
	}
	wa_obj_invalidate(iconlist);
}

/**
* iconlist set anim enable
* @param iconlist
* @param anim_enable
*/
void wa_iconlist_set_anim_enable(wa_obj* iconlist, wa_result anim_enable)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	ext->anim_enable = anim_enable;
}

/**
* iconlist get anim enable
* @param iconlist
* @return anim_enable
*/
wa_result wa_iconlist_get_anim_enable(wa_obj* iconlist)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	return ext->anim_enable;
}

/**
* iconlist set switch time length
* @param iconlist
* @param switch time length
*/
void wa_iconlist_set_switch_time_length(wa_obj* iconlist, uint32_t time)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	ext->switch_time_length = time;
}

/**
* iconlist get switch time length
* @param iconlist
* @return switch time length
*/
uint32_t wa_iconlist_get_switch_time_length(wa_obj* iconlist)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	return ext->switch_time_length;
}

/**
* iconlist set roll type
* @param iconlist
* @param roll type
*/
void wa_iconlist_set_roll_type(wa_obj* iconlist, wa_iconlist_roll_type roll_type)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	ext->roll_type = roll_type;
	wa_obj_invalidate(iconlist);
}

/**
* iconlist get roll type
* @param iconlist
* @return roll type
*/
wa_iconlist_roll_type wa_iconlist_get_roll_type(wa_obj* iconlist)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	return ext->roll_type;
}

/**
* iconlist set text font
* @param iconlist
* @param text font
*/
void wa_iconlist_set_text_font(wa_obj* iconlist, wa_font* font)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	ext->text_font = font;
	wa_obj_invalidate(iconlist);
}

/**
* iconlist get text font
* @param iconlist
* @return text font
*/
wa_font* wa_iconlist_get_tex_font(wa_obj* iconlist)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	return ext->text_font;
}

/**
* iconlist set fore color
* @param iconlist
* @param fore color
*/
void wa_iconlist_set_fore_color(wa_obj* iconlist, wa_gui_color fore_color)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	ext->fore_color = fore_color;
	wa_obj_invalidate(iconlist);
}

/**
* iconlist get fore color
* @param iconlist
* @return fore color
*/
wa_gui_color wa_iconlist_get_fore_color(wa_obj* iconlist)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	return ext->fore_color;
}

/**
* iconlist set back color
* @param iconlist
* @param back color
*/
void wa_iconlist_set_back_color(wa_obj* iconlist, wa_gui_color back_color)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	ext->back_color = back_color;
	wa_obj_invalidate(iconlist);
}

/**
* iconlist get back color
* @param iconlist
* @return back color
*/
wa_gui_color wa_iconlist_get_back_color(wa_obj* iconlist)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	return ext->back_color;
}

/**
* iconlist set select
* @param iconlist
* @param select
*/
void wa_iconlist_set_select(wa_obj* iconlist, uint32_t select)
{
	wa_iconlist_ext* ext;
	wa_area tria_area;
	ext = wa_obj_get_ext_attr(iconlist);
	if (select <= 0)
	{
		select = 0;
	}
	if (select > (ext->option_cnt - 1))
	{
		select = ext->option_cnt - 1;
	}
	if (select == ext->select)
	{
		return;
	}
	if ((ext->select == 0) || (ext->select == (ext->option_cnt - 1))||
		(select == 0) || (select == (ext->option_cnt - 1)))
	{
		int32_t x1 = 0, y1 = 0, x2 = 0, y2 = 0;
		if (ext->roll_type == WA_ICONLIST_ROLL_TYPE_HOR)
		{
			x1 = iconlist->rect.x1 + ext->roll_rel_x - ext->arrow_w - ext->arrow_interval;
			y1 = (ext->roll_h - ext->arrow_h) / 2 + iconlist->rect.y1 + ext->roll_rel_y;
			x2 = iconlist->rect.x1 + ext->roll_rel_x + ext->roll_w + ext->arrow_interval;
			y2 = y1;
		}
		else if (ext->roll_type == WA_ICONLIST_ROLL_TYPE_VER)
		{
			x1 = (ext->roll_w - ext->arrow_w) / 2 + iconlist->rect.x1 + ext->roll_rel_x;
			y1 = iconlist->rect.y1 + ext->roll_rel_y - ext->arrow_h - ext->arrow_interval;
			x2 = x1;
			y2 = iconlist->rect.y1 + ext->roll_rel_y + ext->roll_h + ext->arrow_interval;
		}
		if ((ext->select == 0)||(select == 0))
		{
			tria_area.x1 = x1;
			tria_area.y1 = y1;
			tria_area.x2 = tria_area.x1 + ext->arrow_w - 1;
			tria_area.y2 = tria_area.y1 + ext->arrow_h - 1;
			wa_obj_part_invalidate(iconlist, &tria_area);
		}
		if ((ext->select == (ext->option_cnt - 1)) || (select == (ext->option_cnt - 1)))
		{
			tria_area.x1 = x2;
			tria_area.y1 = y2;
			tria_area.x2 = tria_area.x1 + ext->arrow_w - 1;
			tria_area.y2 = tria_area.y1 + ext->arrow_h - 1;
			wa_obj_part_invalidate(iconlist, &tria_area);
		}
	}
#if USE_WA_ANIM != 0
	if (ext->anim_enable == wa_ok)
	{
		int32_t last_pos;
		int32_t pos;
		char* p;
		int w, h;
		wa_iconlist_invalidate_text(iconlist);

		last_pos = wa_iconlist_select_to_pos(iconlist);
		ext->select = select;
		wa_wm_notify_parent(iconlist, WA_SIGNAL_NOTIFY_SEL_CHANGED);
		pos = wa_iconlist_select_to_pos(iconlist);

		wa_anim_set_var(ext->anim, iconlist);
		wa_anim_set_exec_cb(ext->anim, wa_iconlist_anim_exec_cb);
		wa_anim_set_start_cb(ext->anim, wa_iconlist_anim_start_cb);
		wa_anim_set_finish_cb(ext->anim, wa_iconlist_anim_finish_cb);
		wa_anim_set_path_cb(ext->anim, wa_anim_path_ease_in_out);
		wa_anim_set_time_long(ext->anim, ext->switch_time_length);
		wa_anim_set_early_apply(ext->anim, wa_nok);
		wa_anim_set_values(ext->anim, last_pos, pos);

		p = ext->option_text[ext->select];
		wa_font_get_str_size(&w, &h, (uint8_t*)p, ext->text_font, 0, 0);
		if (ext->text_type == WA_ICONLIST_TEXT_TYPE_NORMAL_HOR)
		{
			ext->text_rel_x = ext->roll_rel_x + (ext->roll_w - w) / 2;
			ext->text_s_x = ext->roll_rel_x + (ext->roll_w - w) / 2;
			ext->text_s_y = iconlist->rect.y2 - iconlist->rect.y1 + 1;
		}
		else if (ext->text_type == WA_ICONLIST_TEXT_TYPE_NORMAL_VER)
		{
			ext->text_rel_y = ext->roll_rel_y + (ext->roll_h - h) / 2;
			ext->text_s_x = iconlist->rect.x2 - iconlist->rect.x1 + 1;
			ext->text_s_y = ext->roll_rel_y + (ext->roll_h - h) / 2;
		}
		ext->text_pos_x = ext->text_s_x;
		ext->text_pos_y = ext->text_s_y;

		wa_anim_start(ext->anim);
	}
	else
#endif
	{
		char* p;
		int w, h;
		wa_area area;
		wa_iconlist_invalidate_text(iconlist);
		ext->select = select;
		wa_wm_notify_parent(iconlist, WA_SIGNAL_NOTIFY_SEL_CHANGED);
		ext->roll_pos = wa_iconlist_select_to_pos(iconlist);
		wa_iconlist_invalidate_bitmap(iconlist);
		p = ext->option_text[ext->select];
		wa_font_get_str_size(&w, &h, (uint8_t*)p, ext->text_font, 0, 0);
		if (ext->text_type == WA_ICONLIST_TEXT_TYPE_NORMAL_HOR)
		{
			area.x1 = iconlist->rect.x1 + ext->roll_rel_x + (ext->roll_w - w) / 2;
			area.y1 = iconlist->rect.y1 + ext->text_rel_y;
			ext->text_pos_x = ext->roll_rel_x + (ext->roll_w - w) / 2;
			ext->text_pos_y = ext->text_rel_y;
		}
		else if (ext->text_type == WA_ICONLIST_TEXT_TYPE_NORMAL_VER)
		{
			area.x1 = iconlist->rect.x1 + ext->text_rel_x;
			area.y1 = iconlist->rect.y1 + ext->roll_rel_y + (ext->roll_h - h) / 2;
			ext->text_pos_x = ext->text_rel_x;
			ext->text_pos_y = ext->roll_rel_y + (ext->roll_h - h) / 2;
		}
		else
		{
			area.x1 = iconlist->rect.x1 + ext->text_rel_x;
			area.y1 = iconlist->rect.y1 + ext->text_rel_y;
			ext->text_pos_x = ext->text_rel_x;
			ext->text_pos_y = ext->text_rel_y;
		}
		area.x2 = area.x1 + w - 1;
		area.y2 = area.y1 + h - 1;
		wa_obj_part_invalidate(iconlist, &area);
	}
}

/**
* iconlist get select
* @param iconlist
* @return select
*/
uint32_t wa_iconlist_get_select(wa_obj* iconlist)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	return ext->select;
}

/**
* iconlist set space
* @param iconlist
* @param space
*/
void wa_iconlist_set_space(wa_obj* iconlist, uint32_t space)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	ext->space = space;
	wa_obj_invalidate(iconlist);
}

/**
* iconlist get space
* @param iconlist
* @return space
*/
uint8_t wa_iconlist_get_space(wa_obj* iconlist)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	return ext->space;
}

/**
* iconlist set roll pos and size
* @param iconlist
* @param x
* @param y
* @param w
* @param h
*/
void wa_iconlist_set_roll_rect(wa_obj* iconlist, int32_t x, int32_t y, int32_t w, int32_t h)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	ext->roll_rel_x = x;
	ext->roll_rel_y = y;
	ext->roll_w = w;
	ext->roll_h = h;
	wa_obj_invalidate(iconlist);
}

/**
* iconlist set text type
* @param iconlist
* @param text_type
*/
void wa_iconlist_set_text_type(wa_obj* iconlist, wa_iconlist_text_type text_type)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	ext->text_type = text_type;
}

/**
* iconlist get text type
* @param iconlist
* @return text_type
*/
wa_iconlist_text_type wa_iconlist_get_text_type(wa_obj* iconlist)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	return ext->text_type;
}

/**
* iconlist set text pos
* @param iconlist
* @param sx
* @param sy
* @param ey
* @param ey
*/
void wa_iconlist_set_text_pos(wa_obj* iconlist, int32_t sx, int32_t sy, int32_t ex, int32_t ey)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	ext->text_s_x = sx;
	ext->text_s_y = sy;
	ext->text_rel_x = ex;
	ext->text_rel_y = ey;
}

/**
* iconlist set arrow enable
* @param iconlist
* @param enable
*/
void wa_iconlist_set_arrow_enable(wa_obj* iconlist, wa_result enable)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	ext->arrow_enable = enable;
	wa_obj_invalidate(iconlist);
}

/**
* iconlist get arrow enable
* @param iconlist
* @return enable
*/
wa_result wa_iconlist_get_arrow_enable(wa_obj* iconlist)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	return ext->arrow_enable;
}

/**
* iconlist set arrow size
* @param iconlist
* @param w
* @param h
* @param interval
*/
void wa_iconlist_set_arrow_size(wa_obj* iconlist, int32_t w, int32_t h, int32_t interval)
{
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	ext->arrow_w = w;
	ext->arrow_h = h;
	ext->arrow_interval = interval;
	wa_obj_invalidate(iconlist);
}

/**
* iconlist init select pos
*/
void wa_iconlist_init_select_pos(wa_obj* iconlist)
{
	wa_iconlist_ext* ext;
	char* p;
	int w, h;
	wa_area area;
	ext = wa_obj_get_ext_attr(iconlist);
	ext->roll_pos = wa_iconlist_select_to_pos(iconlist);
	p = ext->option_text[ext->select];
	wa_font_get_str_size(&w, &h, (uint8_t*)p, ext->text_font, 0, 0);
	if (ext->text_type == WA_ICONLIST_TEXT_TYPE_NORMAL_HOR)
	{
		area.x1 = iconlist->rect.x1 + ext->roll_rel_x + (ext->roll_w - w) / 2;
		area.y1 = iconlist->rect.y1 + ext->text_rel_y;
		ext->text_pos_x = ext->roll_rel_x + (ext->roll_w - w) / 2;
		ext->text_pos_y = ext->text_rel_y;
	}
	else if (ext->text_type == WA_ICONLIST_TEXT_TYPE_NORMAL_VER)
	{
		area.x1 = iconlist->rect.x1 + ext->text_rel_x;
		area.y1 = iconlist->rect.y1 + ext->roll_rel_y + (ext->roll_h - h) / 2;
		ext->text_pos_x = ext->text_rel_x;
		ext->text_pos_y = ext->roll_rel_y + (ext->roll_h - h) / 2;
	}
	else
	{
		area.x1 = iconlist->rect.x1 + ext->text_rel_x;
		area.y1 = iconlist->rect.y1 + ext->text_rel_y;
		ext->text_pos_x = ext->text_rel_x;
		ext->text_pos_y = ext->text_rel_y;
	}
	area.x2 = area.x1 + w - 1;
	area.y2 = area.y1 + h - 1;
	wa_obj_invalidate(iconlist);
}

/**********************
*   STATIC FUNCTIONS
**********************/
#if USE_WA_ANIM != 0
/**
* iconlist anim exec cb
* @param obj
* @param value
*/
static void wa_iconlist_anim_exec_cb(void* obj, int32_t value)
{
	wa_obj* iconlist = (wa_obj*)obj;
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	ext->roll_pos = value;
	wa_iconlist_invalidate_bitmap(iconlist);
	wa_iconlist_invalidate_text(iconlist);
	ext->text_pos_x = ext->text_s_x + (ext->text_rel_x - ext->text_s_x) * (value - ext->anim->start_value) / (ext->anim->end_value - ext->anim->start_value);
	ext->text_pos_y = ext->text_s_y + (ext->text_rel_y - ext->text_s_y) * (value - ext->anim->start_value) / (ext->anim->end_value - ext->anim->start_value);
	wa_iconlist_invalidate_text(iconlist);
}

/**
* iconlist anim finish cb
* @param anim
*/
static void wa_iconlist_anim_finish_cb(wa_anim* anim)
{
	wa_obj* iconlist = (wa_obj*)(anim->var);
	wa_iconlist_ext* ext = wa_obj_get_ext_attr(iconlist);
	if (ext->pid == wa_ok)
	{
		wa_pid_enable(wa_ok);
	}
	if (ext->input == wa_ok)
	{
		wa_input_enable(wa_ok);
	}
}

/**
* iconlist anim start cb
* @param anim
*/
static void wa_iconlist_anim_start_cb(wa_anim* anim)
{
	wa_obj* iconlist = (wa_obj*)(anim->var);
	wa_iconlist_ext* ext = wa_obj_get_ext_attr(iconlist);
	if (wa_pid_is_enable() == wa_ok)
	{
		ext->pid = wa_ok;
		wa_pid_enable(wa_nok);
	}
	else
	{
		ext->pid = wa_nok;
	}

	if (wa_input_is_enable() == wa_ok)
	{
		ext->input = wa_ok;
		wa_input_enable(wa_nok);
	}
	else
	{
		ext->input = wa_nok;
	}
}
#endif

/**
* iconlist invalidate bitmap
* @param iconlist
*/
static void wa_iconlist_invalidate_bitmap(wa_obj* iconlist)
{
	wa_area area;
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	area.x1 = iconlist->rect.x1 + ext->roll_rel_x;
	area.y1 = iconlist->rect.y1 + ext->roll_rel_y;
	area.x2 = area.x1 + ext->roll_w - 1;
	area.y2 = area.y1 + ext->roll_h - 1;
	wa_obj_part_invalidate(iconlist, &area);
}

/**
* iconlist invalidate text
* @param iconlist
*/
static void wa_iconlist_invalidate_text(wa_obj* iconlist)
{
	wa_area area;
	wa_iconlist_ext* ext;
	char* p;
	int w, h;
	ext = wa_obj_get_ext_attr(iconlist);
	if (ext->option_text == NULL)
	{
		return;
	}
	if (ext->text_font == NULL)
	{
		return;
	}
	p = ext->option_text[ext->select];
	wa_font_get_str_size(&w, &h, (uint8_t*)p, ext->text_font, 0, 0);
	area.x1 = iconlist->rect.x1 + ext->text_pos_x;
	area.y1 = iconlist->rect.y1 + ext->text_pos_y;
	area.x2 = area.x1 + w - 1;
	area.y2 = area.y1 + h - 1;
	wa_obj_part_invalidate(iconlist, &area);
}

/**
* iconlist find min voption
* @param iconlist
* @return min voption
*/
static int32_t wa_iconlist_find_min_voption(wa_obj* iconlist)
{
	int w, h;
	uint32_t i;
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	if (ext->roll_type == WA_ICONLIST_ROLL_TYPE_HOR)
	{
		w = 0;
		for (i = 0; i < ext->option_cnt; i++)
		{
			wa_bitmap* p = ext->option_bitmap[i];
			w += wa_bitmap_get_width(p);

			if (ext->roll_pos < w)
			{
				return i;
			}
			w += ext->space;
		}
		return -1;
	}
	else if(ext->roll_type == WA_ICONLIST_ROLL_TYPE_VER)
	{
		h = 0;
		for (i = 0; i < ext->option_cnt; i++)
		{
			wa_bitmap* p = ext->option_bitmap[i];
			h += wa_bitmap_get_height(p);

			if (ext->roll_pos < h)
			{
				return i;
			}
			h += ext->space;
		}
		return -1;
	}
	return -1;
}

/**
* iconlist find max voption
* @param iconlist
* @return max voption
*/
static int32_t wa_iconlist_find_max_voption(wa_obj * iconlist)
{
	int w, h;
	uint32_t i;
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	if (ext->roll_type == WA_ICONLIST_ROLL_TYPE_HOR)
	{
		int width = ext->roll_w;
		w = 0;
		for (i = 0; i < ext->option_cnt; i++)
		{
			wa_bitmap* p = ext->option_bitmap[i];
			w += wa_bitmap_get_width(p);

			if ((ext->roll_pos + width) <= w)
			{
				return i;
			}
			w += ext->space;
		}
		return (ext->option_cnt - 1);
	}
	else if (ext->roll_type == WA_ICONLIST_ROLL_TYPE_VER)
	{
		int height = ext->roll_h;
		h = 0;
		for (i = 0; i < ext->option_cnt; i++)
		{
			wa_bitmap* p = ext->option_bitmap[i];
			h += wa_bitmap_get_height(p);

			if ((ext->roll_pos + height) <= h)
			{
				return i;
			}
			h += ext->space;
		}
		return (ext->option_cnt - 1);
	}
	return -1;
}

/**
* iconlist select to pos
* @param iconlist
* @return pos
*/
static int32_t wa_iconlist_select_to_pos(wa_obj* iconlist)
{
	int32_t w, h;
	uint32_t i;
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(iconlist);
	if (ext->roll_type == WA_ICONLIST_ROLL_TYPE_HOR)
	{
		wa_bitmap* p;
		w = 0;
		for (i = 0; i < ext->select; i++)
		{
			p = ext->option_bitmap[i];
			w += wa_bitmap_get_width(p);
			w += ext->space;
		}
		p = ext->option_bitmap[ext->select];
		return w - (ext->roll_w - wa_bitmap_get_width(p)) / 2;
	}
	else if (ext->roll_type == WA_ICONLIST_ROLL_TYPE_VER)
	{
		wa_bitmap* p;
		h = 0;
		for (i = 0; i < ext->select; i++)
		{
			p = ext->option_bitmap[i];
			h += wa_bitmap_get_height(p);
			h += ext->space;
		}
		p = ext->option_bitmap[ext->select];
		return h - (ext->roll_h - wa_bitmap_get_height(p)) / 2;
	}
	return 0;
}

/**
* iconlist redraw functions
* @param obj
*/
static void _Paint(wa_obj* obj)
{
	uint32_t min, max;
	uint32_t i;
	int32_t x, y;
	uint32_t next_len;
	int32_t start_pos;
	int32_t pw, ph;
	wa_iconlist_ext* ext;
	wa_area str_area;
	char* str_p;
	int sw, sh;

	ext = wa_obj_get_ext_attr(obj);

	pw = wa_obj_get_width(obj);
	ph = wa_obj_get_height(obj);

	wa_mask_fillrect(obj->rect.x1, obj->rect.y1,
		pw,
		ph,
		&(obj->redraw_rect),
		ext->back_color);
	if (ext->option_cnt == 0)
	{
		return;
	}
	if (ext->option_text == NULL)
	{
		return;
	}
	if (ext->text_font == NULL)
	{
		return;
	}
	if (ext->option_bitmap == NULL)
	{
		return;
	}
	min = wa_iconlist_find_min_voption(obj);
	max = wa_iconlist_find_max_voption(obj);

	next_len = 0;
	for (i = 0; i < min; i++)
	{
		wa_bitmap* p = ext->option_bitmap[i];
		if (ext->roll_type == WA_ICONLIST_ROLL_TYPE_HOR)
		{
			next_len += wa_bitmap_get_width(p);
			next_len += ext->space;
		}
		else if (ext->roll_type == WA_ICONLIST_ROLL_TYPE_VER)
		{
			next_len += wa_bitmap_get_height(p);
			next_len += ext->space;
		}
	}
	start_pos = next_len - ext->roll_pos;
	for (i = min; i <= max; i++)
	{
		wa_area area;
		wa_bitmap* p = ext->option_bitmap[i];
		int bw = wa_bitmap_get_width(p);
		int bh = wa_bitmap_get_height(p);
		area.x1 = obj->rect.x1 + ext->roll_rel_x;
		area.y1 = obj->rect.y1 + ext->roll_rel_y;
		area.x2 = area.x1 + ext->roll_w - 1;
		area.y2 = area.y1 + ext->roll_h - 1;
		if (wa_area_union(&area, &area, &(obj->rect)) == wa_ok)
		{
			if (ext->roll_type == WA_ICONLIST_ROLL_TYPE_HOR)
			{
				x = start_pos + obj->rect.x1 + ext->roll_rel_x;
				y = (ext->roll_h - bh) / 2 + obj->rect.y1 + ext->roll_rel_y;

				wa_mask_draw_bitmap(x, y, p, &area, ext->fore_color);

				start_pos += bw;
				start_pos += ext->space;
			}
			else if (ext->roll_type == WA_ICONLIST_ROLL_TYPE_VER)
			{
				x = (ext->roll_w - bw) / 2 + +obj->rect.x1 + ext->roll_rel_x;
				y = start_pos + obj->rect.y1 + ext->roll_rel_y;

				wa_mask_draw_bitmap(x, y, p, &area, ext->fore_color);

				start_pos += bh;
				start_pos += ext->space;
			}
		}
	}

	str_p = ext->option_text[ext->select];
	wa_font_get_str_size(&sw, &sh, (uint8_t*)str_p, ext->text_font, 0, 0);
	str_area.x1 = obj->rect.x1 + ext->text_pos_x;
	str_area.y1 = obj->rect.y1 + ext->text_pos_y;
	str_area.x2 = str_area.x1 + sw - 1;
	str_area.y2 = str_area.y1 + sh - 1;
	wa_mask_dispstr_1(&str_area, (uint8_t*)str_p, ext->text_font, 0, 0, &(obj->redraw_rect), ext->fore_color);

	if (ext->arrow_enable == wa_ok)
	{
		int x1, y1, x2, y2;
		if (ext->roll_type == WA_ICONLIST_ROLL_TYPE_HOR)
		{
			x1 = obj->rect.x1 + ext->roll_rel_x - ext->arrow_w - ext->arrow_interval;
			y1 = (ext->roll_h - ext->arrow_h) / 2 + obj->rect.y1 + ext->roll_rel_y;
			x2 = obj->rect.x1 + ext->roll_rel_x + ext->roll_w + ext->arrow_interval;
			y2 = y1;
			if (ext->select != 0)
			{
				wa_mask_filltriangle(x1, y1, ext->arrow_w, ext->arrow_h, WA_MASK_DRAW_TRIA_LEFT, &(obj->redraw_rect), ext->fore_color);
			}
			if (ext->select != (ext->option_cnt - 1))
			{
				wa_mask_filltriangle(x2, y2, ext->arrow_w, ext->arrow_h, WA_MASK_DRAW_TRIA_RIGHT, &(obj->redraw_rect), ext->fore_color);
			}
		}
		else if (ext->roll_type == WA_ICONLIST_ROLL_TYPE_VER)
		{
			x1 = (ext->roll_w - ext->arrow_w) / 2 + obj->rect.x1 + ext->roll_rel_x;
			y1 = obj->rect.y1 + ext->roll_rel_y - ext->arrow_h - ext->arrow_interval;
			x2 = x1;
			y2 = obj->rect.y1 + ext->roll_rel_y + ext->roll_h + ext->arrow_interval;
			if (ext->select != 0)
			{
				wa_mask_filltriangle(x1, y1, ext->arrow_w, ext->arrow_h, WA_MASK_DRAW_TRIA_UP, &(obj->redraw_rect), ext->fore_color);
			}
			if (ext->select != (ext->option_cnt - 1))
			{
				wa_mask_filltriangle(x2, y2, ext->arrow_w, ext->arrow_h, WA_MASK_DRAW_TRIA_DOWN, &(obj->redraw_rect), ext->fore_color);
			}
		}
	}
}

/**
 * iconlist obj delete function
 * @param obj
 */
static void _Delete(wa_obj* obj)
{
#if USE_WA_ANIM != 0
	wa_iconlist_ext* ext;
	ext = wa_obj_get_ext_attr(obj);
	if (ext->anim != NULL)
	{
		wa_free(ext->anim);
	}
#endif
	wa_iconlist_clear_option(obj);
}

/**
 * iconlist obj callback function
 * @param sign
 */
static void wa_iconlist_callback(wa_sign* sign)
{
	int sign_id;
	wa_obj* obj;

	ancestor_callback(sign);
	sign_id = sign->sign_id;
	obj = sign->obj_dst;

	switch (sign_id)
	{
		case WA_SIGNAL_PAINT:
		{
			_Paint(obj);
			break;
		}
		case WA_SIGNAL_DELETE:
		{
			_Delete(obj);
			break;
		}
		default:
		{
			break;
		}
	}
}

#endif
